
import type { Ref } from 'vue'

import type {
  IAnyObject,
  IFormChildPropsList,
  IFormChildOnlyPropsList,
  IFormChildMetaList
} from './20-form-child'

import type { ESubType } from './enum'


// 表单控件 ==========================================================

/**
 * 显示控件的联动设置
 */
export interface ILinkageMeta {
  /**
   * 控件的ID作为key，每个控件值对应一个数组，数组里面是需要显示的控件ID。
   */
  [key: string | number]: {
    /**
     * 控件的值作为key，后面的数组里存放需要显示的控件ID
     */
    [id: string | number ]: Array<number>
  }
}

/**
  string: Must be of type string. This is the default type.
  number: Must be of type number.
  boolean: Must be of type boolean.
  method: Must be of type function.
  regexp: Must be an instance of RegExp or a string that does not generate an exception when creating a new RegExp.
  integer: Must be of type number and an integer.
  float: Must be of type number and a floating point number.
  array: Must be an array as determined by Array.isArray.
  object: Must be of type object and not Array.isArray.
  enum: Value must exist in the enum.
  date: Value must be valid as determined by Date
  url: Must be of type url.
  hex: Must be of type hex.
  email: Must be of type email.
  any：Can be any type.
*/
type IRuleType = 
  | 'string'
  | 'number'
  | 'boolean'
  | 'method'
  | 'regexp'
  | 'integer'
  | 'float'
  | 'array'
  | 'object'
  | 'enum'
  | 'date'
  | 'url'
  | 'hex'
  | 'email'
  | 'any'
  

/**
 * 一条验证规则，一个字段可以有多条验证规则
 * * trigger
 * * message
 * * 其他
 */
export interface IRule {
  /**
   * 验证时机：blur、change 
   */
  trigger?: "blur" | "change" | "click" | "keyup",
  /**
   * 提示消息
   */
  message?: string,
  /**
   * 必填
   */
  required?: boolean,
  /**
   * 数据类型：any、date、url等
   */
  type?: IRuleType,
  /**
   * 长度
   */
  len?: number, // 长度
  /**
   * 最大值
   */
  max?: number,
  /**
   * 最小值
   */
  min?: number,
  /**
   * 正则
   */
  pattern?: string
}


/**
 * 表单的验证规则集合
 * * key: string | number: IRule[]
 * * 一个key，对应一个字段
 */
export interface IRuleMeta {
  /**
   * 控件的ID作为key， 一个控件，可以有多条验证规则
   */
  [key: string | number]: Array<IRule>
}

/**
 * 分栏表单的设置
 */
export interface ISubMeta {
  type: ESubType, // 分栏类型：card、tab、step、"" （不分栏）
  cardColCount: number, // 分几栏目
  cols: Array<{ // 栏目信息
    title: string, // 栏目名称
    colIds:  Array<number> // 栏目里有哪些控件ID
  }>
}

/**
 * 表单需要的 meta
 * * moduleId、formId、columnsNumber、
 * * colOrder: Array<number | string>,
 * * subMeta?: ISubMeta,
 * * ruleMeta: IRuleMeta,
 * * linkageMeta: ILinkageMeta,
 * * customerControl?: any,
 */
export interface IFromMeta {
  /**
   * 模块编号，综合使用的时候需要
   */
  moduleId: number | string,
  /**
   * 表单编号，一个模块可以有多个表单
   */
  formId: number | string,
  /**
   * 显示哪些字段，以及字段的先后顺序，Array<number | string>,
   */
  colOrder: Array<number | string>,
  /**
   * 表单的列数，分为几列 number,
   */
  columnsNumber: 1 | 2 | 3 | 4 | 6 | 8 | 12
  /**
   * 分栏的设置，ISubMeta
   */
  subMeta?: ISubMeta,
  /**
   * 验证信息，IRuleMeta （直接使用）
   */
  ruleMeta: IRuleMeta,
  /**
   * 子控件的联动关系，ILinkageMeta
   */
  // formColShow: IFormColShow,
  linkageMeta: ILinkageMeta,
  /*
  * 自定义子控件 key:value形式
  * * key: 编号。1：插槽；100-200：保留编号
  * * value：string：标签；函数：异步组件，类似路由的设置
  */
  customerControl?: any,
  /**
   * 是否重新加载配置，需要来回取反，boolean
   */
  reload?: boolean,
  /**
   * () => void
   */
  reset?: () => void,
  /**
   * () => void
   */
  events?: () => void
}

/**
 * 表单控件的 props
 * * formMeta: IFromMeta,
 * * childPropsList: IFormChildPropsList,
 * * 其他 el-form 的 props
 */
export interface IFromProps<T extends IAnyObject> {
  /**
   * 表单的 model，对象，包含多个字段。
   */
  model: T,
  /**
   * 根据选项过滤后的 model,any
   */
  partModel?: any,
  /**
   * 表单控件需要的 meta
   */
  formMeta: IFromMeta,
  /**
   * 表单子控件的属性，IFormItem
   * itemMeta 更名： childPropsList
   */
  childPropsList: IFormChildPropsList,
  /**
   * 标签的后缀，string
   */
  labelSuffix?: string,
  /**
  * 标签的宽度，string
  */
  labelWidth?: string,
  /**
  * 其他扩展属性
  */
  [propName: string]: any
 
}

/**
 * 一个字段占据几个 格子
 */
export interface FormColSpan {
  [id: number]: number
}

/**
 * 显示字段的依据
 */
export interface  ShowCol {
  [id: number | string]: boolean
}

/**
 * 表单控件内部需要的状态
 * * model: T
 * * partModel: IAnyObject
 * * columnsNumber() 列数
 * * ruleMeta: IRuleMeta,
 * * linkageMeta：联动筛选
 * * childPropsList: IFormChildPropsList,input 的 props 集合
 * * childMetaList: IFormChildMetaList,input 等的纯 meta 集合
 * * formColSpan: {[key: number | string]: number} ,一个字段占多少 span
 * * showCol: {[key: number | string]: boolean}, 是否显示字段
 */
export interface IFormState<T> {
  /**
   * props 传入的表单 model
   */
  model: T,
  /**
   * 筛选后的 model
   */
  partModel?: IAnyObject,
  // 来自 配置
  /**
   * 来自配置 formMeta，确定表单的列数
   */
  columnsNumber: () => number
  /**
   * 来自配置的 formMeta
   */
  formMeta: IFromMeta,
  /**
   * 来自 配置 的 验证规则
   */
  ruleMeta: IRuleMeta,
  /**
   * 来自配置的 排序字段ID
   */
  colOrder: Array<string | number>,
  /**
   * 来自配置的 联动筛选的设置
   */
  linkageMeta: ILinkageMeta,
  // 调整
  /**
   * input 的 props 的集合，不含 meta
   */
  childPropsList: IFormChildOnlyPropsList,
  /**
   * input  的 meta 集合
   */
  childMetaList: IFormChildMetaList,
  // 创建
  /**
   * 根据 columnsNumber 和 input 的 meta 计算出来一个字段占多少 span
   */
  formColSpan: FormColSpan,
  /**
   * 联动筛选时，字段是否可见
   */
  showCol: ShowCol
}